/*
 * 在 Orchard Core 中，如果你想管理资源文件，可以使用 Media 功能，
 * 它允许你在仪表板中管理租户的 Media 文件夹。
 * 如果启用 OrchardCore.Media.Azure，则存储将为 Azure Blob Storage。
 * 但如果你想直接在代码中上传、删除或读取文件，甚至操作 Media 文件夹外的文件怎么办？
 *
 * 有一个名为 IFileStore 的服务，但它默认未注册到服务容器。
 * 需要文件操作的功能会有自己的服务继承自 IFileStore（或依赖于它）。
 * 例如 IMediaFileStore 可用于管理 Media 文件夹中的文件。
 * 如果需要管理任意文件系统路径下的文件，需要自定义服务并指定根路径。
 */

using Ruitu.Edu.TrainingDemo.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;
using OrchardCore.DisplayManagement.Notify;
using OrchardCore.FileStorage;
using OrchardCore.Media;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace Ruitu.Edu.TrainingDemo.Controllers;

/// <summary>
/// 文件管理控制器 - 演示 Orchard Core 文件与媒体管理机制
/// 
/// 主要用途：
/// - 演示如何通过代码管理 Media 文件夹中的文件
/// - 展示自定义文件存储服务的用法
/// - 演示文件上传、读取、创建等操作
/// 
/// 使用场景：
/// - 需要在代码中上传/读取/删除文件
/// - 管理 Media 文件夹或自定义文件夹下的文件
/// 
/// 设计原因：
/// - 利用 IMediaFileStore 实现媒体文件管理
/// - 通过自定义 IFileStore 实现任意路径文件操作
/// 
/// 设计模式：
/// - 依赖注入模式：通过构造函数注入文件存储服务
/// - 服务封装模式：将文件操作逻辑封装在服务中
/// </summary>
public sealed class FileManagementController : Controller
{
    // 路径常量，避免重复硬编码。
    private const string TestFileRelativePath = "TrainingDemo/TestFile1.txt";
    private const string UploadedFileFolderRelativePath = "TrainingDemo/Uploaded";

    private readonly IMediaFileStore _mediaFileStore;
    private readonly INotifier _notifier;
    private readonly IHtmlLocalizer H;
    private readonly ICustomFileStore _customFileStore;

    /// <summary>
    /// 构造函数 - 注入所需服务
    /// </summary>
    public FileManagementController(
        IMediaFileStore mediaFileStore,
        INotifier notifier,
        IHtmlLocalizer<FileManagementController> htmlLocalizer,
        ICustomFileStore customFileStore)
    {
        _mediaFileStore = mediaFileStore;
        _notifier = notifier;
        _customFileStore = customFileStore;
        H = htmlLocalizer;
    }

    /// <summary>
    /// 在 Media 文件夹中创建文件并读取
    /// 访问路径：/Ruitu.Edu.TrainingDemo/FileManagement/CreateFileInMediaFolder
    /// </summary>
    public async Task<string> CreateFileInMediaFolder()
    {
        // 使用内存流写入文本内容到文件。
        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("Hi there!")))
        {
            await _mediaFileStore.CreateFileFromStreamAsync(TestFileRelativePath, stream, overwrite: true);
        }
        // 检查文件是否存在。
        var fileInfo = await _mediaFileStore.GetFileInfoAsync(TestFileRelativePath);
        // 获取文件的公开 URL。
        var publicUrl = _mediaFileStore.MapPathToPublicUrl(TestFileRelativePath);
        return $"Successfully created file! File size: {fileInfo.Length} bytes. Public URL: {publicUrl}";
    }

    /// <summary>
    /// 读取 Media 文件夹中的文件内容
    /// 访问路径：/Ruitu.Edu.TrainingDemo/FileManagement/ReadFileFromMediaFolder
    /// </summary>
    public async Task<string> ReadFileFromMediaFolder()
    {
        if (await _mediaFileStore.GetFileInfoAsync(TestFileRelativePath) == null)
        {
            return "Create the file first!";
        }
        using var stream = await _mediaFileStore.GetFileStreamAsync(TestFileRelativePath);
        using var streamReader = new StreamReader(stream);
        var content = await streamReader.ReadToEndAsync(HttpContext.RequestAborted);
        return $"File content: {content}";
    }

    /// <summary>
    /// 文件上传页面 - 演示文件上传到 Media 文件夹
    /// 访问路径：/Ruitu.Edu.TrainingDemo/FileManagement/UploadFileToMedia
    /// </summary>
    public ActionResult UploadFileToMedia() => View();

    /// <summary>
    /// 文件上传 POST 操作
    /// </summary>
    [HttpPost, ActionName(nameof(UploadFileToMedia)), ValidateAntiForgeryToken]
    public async Task<ActionResult> UploadFileToMediaPost(IFormFile file)
    {
        if (!ModelState.IsValid || file == null) return BadRequest();
        var mediaFilePath = _mediaFileStore.Combine(UploadedFileFolderRelativePath, file.FileName);
        using (var stream = file.OpenReadStream())
        {
            await _mediaFileStore.CreateFileFromStreamAsync(mediaFilePath, stream);
        }
        await _notifier.InformationAsync(H["Successfully uploaded file!"]);
        return RedirectToAction(nameof(UploadFileToMedia));
    }

    // 下一站：Services/CustomFileStore.cs

    /// <summary>
    /// 在自定义文件夹中创建文件
    /// 访问路径：/Ruitu.Edu.TrainingDemo/FileManagement/CreateFileInCustomFolder
    /// </summary>
    public async Task<string> CreateFileInCustomFolder()
    {
        using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("Hi there in the custom file storage!")))
        {
            await _customFileStore.CreateFileFromStreamAsync(TestFileRelativePath, stream, overwrite: true);
        }
        var fileInfo = await _customFileStore.GetFileInfoAsync(TestFileRelativePath);
        return $"Successfully created file in the custom file storage! File size: {fileInfo.Length} bytes.";
    }
}

// 训练部分结束：文件管理
// 下一站：Services/DemoBackgroundTask.cs
